home *** CD-ROM | disk | FTP | other *** search
/ Cream of the Crop 20 / Cream of the Crop 20 (Terry Blount) (1996).iso / program / freeli20.zip / freelib2.asx < prev    next >
Text File  |  1996-07-01  |  73KB  |  2,711 lines

  1. ~~~C_STR1
  2. Ideal
  3.  
  4. Public      strlen,strcpy,strcat,strcmp
  5.  
  6. Model Tiny
  7. CodeSeg
  8. P186
  9.  
  10. ;****************** strlen() -- Get length of string
  11. ;int strlen(char *strp);
  12.  
  13. strp        equ bp+4
  14.  
  15. Proc        strlen
  16.  
  17.             push bp                 ;Set up stack frame
  18.             mov bp,sp
  19.             push si                 ;Save SI
  20.  
  21.             mov si,[strp]           ;SI = string pointer
  22.  
  23. p1_loop:    lodsb                   ;Load char
  24.             test al,al              ;Loop while not zero
  25.             jnz p1_loop
  26.  
  27.             sub si,[strp]           ;AX = length
  28.             dec si
  29.             xchg ax,si
  30.  
  31.             pop si                  ;Restore SI
  32.             pop bp                  ;Delete stack frame
  33.             ret 2                   ;Return
  34.  
  35. EndP        strlen
  36.  
  37. ;****************** strcpy() -- Copy a string
  38. ;void strcpy(char *str1, char *str2);
  39.  
  40. str1        equ bp+6
  41. str2        equ bp+4
  42.  
  43. Proc        strcpy
  44.  
  45.             push bp                 ;Set up stack frame
  46.             mov bp,sp
  47.             pusha                   ;Save all registers
  48.  
  49.             mov si,[str2]           ;SI = source
  50.             mov di,[str1]           ;DI = destination
  51.  
  52. p2_loop:    lodsb                   ;Load char
  53.             mov [di],al             ;Store char
  54.             inc di
  55.             test al,al              ;Loop while not zero
  56.             jnz p2_loop
  57.  
  58.             popa                    ;Restore registers
  59.             pop bp                  ;Delete stack frame
  60.             ret 4                   ;Return
  61.  
  62. EndP        strcpy
  63.  
  64. ;****************** strcat() -- Concatenate strings
  65. ;void strcat(char *str1, char *str2);
  66.  
  67. str1        equ bp+6
  68. str2        equ bp+4
  69.  
  70. Proc        strcat
  71.  
  72.             push bp                 ;Set up stack frame
  73.             mov bp,sp
  74.             pusha                   ;Save all registers
  75.  
  76.             mov si,[str1]           ;SI = destination
  77.  
  78. p3_cloop:   lodsb                   ;Load char
  79.             test al,al              ;Loop while not zero
  80.             jnz p3_cloop
  81.  
  82.             mov di,si               ;DI = destination
  83.             mov si,[str2]           ;SI = source
  84.             dec di
  85.  
  86. p3_loop:    lodsb                   ;Load char
  87.             mov [di],al             ;Store char
  88.             inc di
  89.             test al,al              ;Loop while not zero
  90.             jnz p3_loop
  91.  
  92.             popa                    ;Restore registers
  93.             pop bp                  ;Delete stack frame
  94.             ret 4                   ;Return
  95.  
  96. EndP        strcat
  97.  
  98. ;****************** strcmp() -- Compare strings
  99. ;void strcmp(char *str1, char *str2);
  100.  
  101. str1        equ bp+6
  102. str2        equ bp+4
  103.  
  104. Proc        strcmp
  105.  
  106.             push bp                 ;Set up stack frame
  107.             mov bp,sp
  108.             push si di              ;Save registers
  109.  
  110.             mov si,[str1]           ;SI = source
  111.             mov di,[str2]           ;DI = destination
  112.  
  113. p4_loop:    lodsb                   ;Load char 1
  114.             mov ah,[di]             ;Load char 2
  115.             inc di
  116.             cmp al,ah               ;Not equal?
  117.             jne p4_nope
  118.             test al,al              ;Loop while not zero
  119.             jnz p4_loop
  120.  
  121.             xor ax,ax               ;Equal, return 0
  122. p4_done:    pop di si               ;Restore registers
  123.             pop bp                  ;Delete stack frame
  124.             ret 4                   ;Return
  125.  
  126. p4_nope:    sub al,ah               ;Not equal, return difference
  127.             cbw                     ;in first unequal position
  128.             jmp p4_done
  129.  
  130. EndP        strcmp
  131.  
  132. End
  133.  
  134. ~~~C_STR2
  135. Ideal
  136.  
  137. Extrn       strlen:near
  138. Public      strchr,strstr
  139.  
  140. Model Tiny
  141. CodeSeg
  142. P186
  143.  
  144. ;****************** strchr() -- Search string for char
  145. ;int strchr(char *strp, int chr);
  146.  
  147. strp        equ bp+6
  148. chr         equ bp+4
  149.  
  150. Proc        strchr
  151.  
  152.             push bp                 ;Set up stack frame
  153.             mov bp,sp
  154.             push si                 ;Save SI
  155.  
  156.             mov si,[strp]           ;SI = string pointer
  157.             mov ah,[chr]            ;AH = char
  158.  
  159. p1_loop:    lodsb                   ;Load char
  160.             test al,al              ;Null, not found
  161.             jz p1_nope
  162.             cmp al,ah               ;Loop while not equal
  163.             jne p1_loop
  164.  
  165.             sub si,[strp]           ;AX = position of char
  166.             dec si
  167.             xchg ax,si
  168.  
  169. p1_done:    pop si                  ;Restore SI
  170.             pop bp                  ;Delete stack frame
  171.             ret 4                   ;Return
  172.  
  173. p1_nope:    mov ax,-1               ;Not found, return -1
  174.             jmp p1_done
  175.  
  176. EndP        strchr
  177.  
  178. ;****************** strstr() -- Search string for substring
  179. ;int strstr(char *strp, char *subp);
  180.  
  181. strp        equ bp+6
  182. subp        equ bp+4
  183.  
  184. Proc        strstr
  185.  
  186.             push bp                 ;Set up stack frame
  187.             mov bp,sp
  188.             push es                 ;Save registers
  189.             pusha
  190.  
  191.             push ds                 ;ES = DS
  192.             pop es
  193.  
  194.             mov si,[strp]           ;SI = string pointer
  195.             mov bx,[subp]           ;BX = substring pointer
  196.             push bx                 ;Get length of substring
  197.             call strlen             ;into DX
  198.             xchg dx,ax
  199.             mov ah,[bx]             ;AH = first char
  200.  
  201. p3_loop:    lodsb                   ;Load char
  202.             test al,al              ;Null, not found
  203.             jz p3_nope
  204.             cmp al,ah               ;Loop while not equal
  205.             jne p3_loop
  206.  
  207.             mov cx,dx               ;CX = length
  208.             mov di,bx               ;DI = substring
  209.             push si                 ;Save SI
  210.             dec si                  ;Push back char
  211.             repe cmpsb              ;Compare strings
  212.             pop si                  ;Restore SI
  213.             jne p3_loop             ;Loop if not equal
  214.  
  215.             sub si,[strp]           ;AX = position of char
  216.             dec si
  217.             
  218. p3_done:    mov es,si               ;Pipe through ES
  219.             popa                    ;Restore registers
  220.             mov ax,es               ;Return value in AX
  221.             pop es
  222.             pop bp                  ;Delete stack frame
  223.             ret 4                   ;Return
  224.  
  225. p3_nope:    mov si,-1               ;Not found, return -1
  226.             jmp p3_done
  227.  
  228. EndP        strstr
  229.  
  230. End
  231.  
  232. ~~~C_STR3
  233. Ideal
  234.  
  235. Public      stricmp,strlwr,strupr
  236.  
  237. Model Tiny
  238. CodeSeg
  239. P186
  240.  
  241. ;****************** stricmp() -- Compare strings, case insensitive
  242. ;void stricmp(char *str1, char *str2);
  243.  
  244. str1        equ bp+6
  245. str2        equ bp+4
  246.  
  247. Proc        stricmp
  248.  
  249.             push bp                 ;Set up stack frame
  250.             mov bp,sp
  251.             push si di              ;Save registers
  252.  
  253.             mov si,[str1]           ;SI = source
  254.             mov di,[str2]           ;DI = destination
  255.  
  256. p1_loop:    lodsb                   ;Load char 1
  257.             mov ah,[di]             ;Load char 2
  258.             inc di
  259.  
  260.             cmp al,'a'              ;Convert AL to uppercase
  261.             jb p1_setAH
  262.             cmp al,'z'
  263.             ja p1_setAH
  264.             sub al,20h
  265.  
  266. p1_setAH:   cmp ah,'a'              ;Convert AH to uppercase
  267.             jb p1_comp
  268.             cmp ah,'z'
  269.             ja p1_comp
  270.             sub ah,20h
  271.  
  272. p1_comp:    cmp al,ah               ;Equal?
  273.             jne p1_nope
  274.             test al,al              ;Loop while not zero
  275.             jnz p1_loop
  276.  
  277.             inc ax                  ;Equal, return 1
  278.  
  279. p1_done:    pop di si               ;Restore registers
  280.             pop bp                  ;Delete stack frame
  281.             ret 4                   ;Return
  282.  
  283. p1_nope:    xor ax,ax               ;Not equal, return 0
  284.             jmp p1_done
  285.  
  286. EndP        stricmp
  287.  
  288. ;****************** strlwr() -- Convert string to lowercase
  289. ;int strlwr(char *strp);
  290.  
  291. strp        equ bp+4
  292.  
  293. Proc        strlwr
  294.  
  295.             push bp                 ;Set up stack frame
  296.             mov bp,sp
  297.             pusha                   ;Save registers
  298.  
  299.             mov si,[strp]           ;SI = string pointer
  300.  
  301. p2_loop:    lodsb                   ;Load char
  302.             test al,al              ;Check for null
  303.             jz p2_done
  304.             cmp al,'A'              ;Check for uppercase
  305.             jb p2_loop
  306.             cmp al,'Z'
  307.             ja p2_loop
  308.             add al,20h              ;Convert to lowercase
  309.             mov [si-1],al           ;Store char
  310.             jmp p2_loop
  311.  
  312. p2_done:    popa                    ;Restore registers
  313.             pop bp                  ;Delete stack frame
  314.             ret 2                   ;Return
  315.  
  316. EndP        strlwr
  317.  
  318. ;****************** strupr() -- Convert string to uppercase
  319. ;int strupr(char *strp);
  320.  
  321. strp        equ bp+4
  322.  
  323. Proc        strupr
  324.  
  325.             push bp                 ;Set up stack frame
  326.             mov bp,sp
  327.             pusha                   ;Save registers
  328.  
  329.             mov si,[strp]           ;SI = string pointer
  330.  
  331. p3_loop:    lodsb                   ;Load char
  332.             test al,al              ;Check for null
  333.             jz p3_done
  334.             cmp al,'a'              ;Check for lowercase
  335.             jb p3_loop
  336.             cmp al,'z'
  337.             ja p3_loop
  338.             sub al,20h              ;Convert to uppercase
  339.             mov [si-1],al           ;Store char
  340.             jmp p3_loop
  341.  
  342. p3_done:    popa                    ;Restore registers
  343.             pop bp                  ;Delete stack frame
  344.             ret 2                   ;Return
  345.  
  346. EndP        strupr
  347.  
  348. End
  349.  
  350. ~~~C_STR4
  351. Ideal
  352.  
  353. Public      strrtrim,strltrim
  354.  
  355. Model Tiny
  356. CodeSeg
  357. P186
  358.  
  359. ;****************** strrtrim() -- Trim trailing spaces off a string
  360. ;int strrtrim(char *strp);
  361.  
  362. strp        equ bp+4
  363.  
  364. Proc        strrtrim
  365.  
  366.             push bp                 ;Set up stack frame
  367.             mov bp,sp
  368.             pusha                   ;Save registers
  369.  
  370.             mov si,[strp]           ;SI = string pointer
  371.             mov di,si               ;DI = SI
  372.  
  373. p1_loop:    lodsb                   ;Load char
  374.             test al,al              ;Check for null
  375.             jz p1_done
  376.             cmp al,' '              ;Check for space
  377.             je p1_loop
  378.             mov di,si               ;Set pointer
  379.             jmp p1_loop
  380.  
  381. p1_done:    mov [byte di+1],al      ;Terminate string
  382.             popa                    ;Restore registers
  383.             pop bp                  ;Delete stack frame
  384.             ret 2                   ;Return
  385.  
  386. EndP        strrtrim
  387.  
  388. ;****************** strltrim() -- Trim leading spaces off a string
  389. ;int strltrim(char *strp);
  390.  
  391. strp        equ bp+4
  392.  
  393. Proc        strltrim
  394.  
  395.             push bp                 ;Set up stack frame
  396.             mov bp,sp
  397.             pusha                   ;Save registers
  398.  
  399.             mov si,[strp]           ;SI, DI = string pointer
  400.             mov di,si
  401.  
  402. p2_loop:    lodsb                   ;Load char
  403.             test al,al              ;Check for null
  404.             jz p2_cont
  405.             cmp al,' '              ;Loop while space
  406.             je p2_loop
  407.  
  408. p2_cont:    dec si                  ;Move back one char
  409.             cmp si,di               ;No spaces, quit
  410.             je p2_done
  411.  
  412. p2_cloop:   lodsb                   ;Shift the string over
  413.             mov [di],al
  414.             inc di
  415.             test al,al
  416.             jnz p2_cloop
  417.  
  418. p2_done:    popa                    ;Restore registers
  419.             pop bp                  ;Delete stack frame
  420.             ret 2                   ;Return
  421.  
  422. EndP        strltrim
  423.  
  424. End
  425.  
  426. ~~~C_MEM1
  427. Ideal
  428.  
  429. Public      memcpy,memset
  430.  
  431. Model Tiny
  432. CodeSeg
  433. P186
  434.  
  435. ;****************** memcpy() -- Copy memory block
  436. ;void memcpy(void *p1, void *p2, int nbytes);
  437.  
  438. p1          equ bp+8
  439. p2          equ bp+6
  440. nbytes      equ bp+4
  441.  
  442. Proc        memcpy
  443.  
  444.             push bp                 ;Set up stack frame
  445.             mov bp,sp
  446.             push es                 ;Save registers
  447.             pusha
  448.  
  449.             push ds                 ;ES = DS
  450.             pop es
  451.  
  452.             mov si,[p2]             ;SI = source
  453.             mov di,[p1]             ;DI = destination
  454.             mov cx,[nbytes]         ;CX = count
  455.  
  456.             cmp di,si               ;Make forward moves
  457.             jb p1_go                ;in reverse
  458.             je p1_done
  459.  
  460.             std                     ;Set direction flag
  461.             add si,cx               ;Move offsets to end
  462.             add di,cx
  463.             dec si
  464.             dec di
  465.  
  466. p1_go:      rep movsb               ;Copy memory
  467.  
  468. p1_done:    cld                     ;Clear direction flag
  469.             popa                    ;Restore registers
  470.             pop es
  471.             pop bp                  ;Delete stack frame
  472.             ret 6                   ;Return
  473.  
  474. EndP        memcpy
  475.  
  476. ;****************** memset() -- Set memory block
  477. ;void memset(void *ptr, int nbytes, int chr);
  478.  
  479. ptr         equ bp+8
  480. nbytes      equ bp+6
  481. chr         equ bp+4
  482.  
  483. Proc        memset
  484.  
  485.             push bp                 ;Set up stack frame
  486.             mov bp,sp
  487.             push es                 ;Save registers
  488.             pusha
  489.  
  490.             push ds                 ;ES = DS
  491.             pop es
  492.  
  493.             mov di,[ptr]            ;DI = block
  494.             mov cx,[nbytes]         ;CX = count
  495.             mov al,[chr]            ;AL = char
  496.             rep stosb               ;Set memory
  497.  
  498.             popa                    ;Restore registers
  499.             pop es
  500.             pop bp                  ;Delete stack frame
  501.             ret 6                   ;Return
  502.  
  503. EndP        memset
  504.  
  505. End
  506.  
  507. ~~~C_MEM2
  508. Ideal
  509.  
  510. Public      memcmp,memchr
  511.  
  512. Model Tiny
  513. CodeSeg
  514. P186
  515.  
  516. ;****************** memcmp() -- Compare memory blocks
  517. ;void memcmp(void *p1, void *p2, int nbytes);
  518.  
  519. p1          equ bp+8
  520. p2          equ bp+6
  521. nbytes      equ bp+4
  522.  
  523. Proc        memcmp
  524.  
  525.             push bp                 ;Set up stack frame
  526.             mov bp,sp
  527.             push es                 ;Save registers
  528.             push cx si di
  529.  
  530.             push ds                 ;ES = DS
  531.             pop es
  532.  
  533.             mov si,[p2]             ;SI = source
  534.             mov di,[p1]             ;DI = destination
  535.             mov cx,[nbytes]         ;CX = count
  536.             repe cmpsb              ;Compare memory
  537.  
  538.             mov ax,1                ;Assume equal
  539.             je p1_done              ;Jump if equal
  540.  
  541.             xor ax,ax               ;Not equal, return 0
  542.  
  543. p1_done:    pop di si cx            ;Restore registers
  544.             pop es
  545.             pop bp                  ;Delete stack frame
  546.             ret 6                   ;Return
  547.  
  548. EndP        memcmp
  549.  
  550. ;****************** memchr() -- Scan memory for char
  551. ;void memchr(void *ptr, int nbytes, int chr);
  552.  
  553. ptr         equ bp+8
  554. nbytes      equ bp+6
  555. chr         equ bp+4
  556.  
  557. Proc        memchr
  558.  
  559.             push bp                 ;Set up stack frame
  560.             mov bp,sp
  561.             push es                 ;Save registers
  562.             push cx si di
  563.  
  564.             push ds                 ;ES = DS
  565.             pop es
  566.  
  567.             mov di,[ptr]            ;DI = block
  568.             mov cx,[nbytes]         ;CX = count
  569.             mov al,[chr]            ;AL = char
  570.             repne scasb             ;Scan memory
  571.             jne p2_nope             ;Jump if not found
  572.  
  573.             sub di,[ptr]            ;AX = position of char
  574.             dec di
  575.             xchg ax,di
  576.  
  577. p2_done:    pop di si cx            ;Restore registers
  578.             pop es
  579.             pop bp                  ;Delete stack frame
  580.             ret 6                   ;Return
  581.  
  582. p2_nope:    mov ax,-1               ;Not found, return -1
  583.             jmp p2_done
  584.  
  585. EndP        memchr
  586.  
  587. End
  588.  
  589. ~~~C_ISRCH
  590. Ideal
  591.  
  592. Public      isearch
  593.  
  594. Model Tiny
  595. P186
  596. CodeSeg
  597.  
  598. ;****************** isearch() -- Search a sorted array of integers
  599. ;int isearch(int *ary, int size, int elem);
  600.  
  601. ary         equ bp+8
  602. size        equ bp+6
  603. elem        equ bp+4
  604.  
  605. Proc        isearch
  606.  
  607.             push bp                 ;Set up stack frame
  608.             mov bp,sp
  609.             push bx cx dx si di     ;Save registers
  610.  
  611.             mov bx,[ary]            ;BX = array
  612.             xor cx,cx               ;CX = lower limit
  613.             mov dx,[size]           ;DX = upper limit
  614.             dec dx
  615.  
  616. p1_loop:    mov si,cx               ;SI = middle element
  617.             add si,dx
  618.             shr si,1
  619.             add si,si
  620.             mov ax,[bx+si]          ;Get element
  621.             shr si,1                ;Fix SI
  622.             cmp ax,[elem]           ;Check element
  623.             je p1_found             ;Equal?
  624.             jl p1_less              ;Too low?
  625.  
  626. p1_greater: mov di,si               ;Set first half
  627.             mov si,cx
  628.             jmp p1_cont
  629.  
  630. p1_less:    mov di,dx               ;Set second half
  631.             inc si
  632.  
  633. p1_cont:    cmp cx,dx               ;Min = Max, done
  634.             je p1_nope
  635.             mov cx,si               ;Set limits
  636.             mov dx,di
  637.             jmp p1_loop             ;Loop back
  638.  
  639. p1_found:   xchg ax,si              ;AX = result
  640.  
  641. p1_done:    pop di si dx cx bx      ;Restore registers
  642.             pop bp                  ;Delete stack frame
  643.             ret 6                   ;Return
  644.  
  645. p1_nope:    mov ax,-1               ;Not found, return -1
  646.             jmp p1_done
  647.  
  648. EndP        isearch
  649.  
  650. End
  651.  
  652. ~~~C_LSRCH
  653. Ideal
  654.  
  655. Public      lsearch
  656.  
  657. Model Tiny
  658. P186
  659. CodeSeg
  660.  
  661. ;****************** lsearch() -- Search a sorted array of longs
  662. ;int lsearch(long *ary, int size, long elem);
  663.  
  664. ary         equ bp+10
  665. size        equ bp+8
  666. elem        equ bp+4
  667.  
  668. Proc        lsearch
  669.  
  670.             push bp                 ;Set up stack frame
  671.             mov bp,sp
  672.             push bx cx dx si di     ;Save registers
  673.  
  674.             mov bx,[ary]            ;BX = array
  675.             xor cx,cx               ;CX = lower limit
  676.             mov dx,[size]           ;DX = upper limit
  677.             dec dx
  678.  
  679. p1_loop:    mov si,cx               ;SI = middle element
  680.             add si,dx
  681.             shr si,1
  682.             shl si,2
  683.             mov ax,[bx+si]          ;Get element
  684.             mov di,[bx+si+2]
  685.             shr si,2                ;Fix SI
  686.  
  687.             cmp di,[elem+2]         ;Check high word
  688.             jl p1_less              ;Too low?
  689.             jg p1_greater           ;Too high?
  690.             cmp ax,[elem]           ;Check low word
  691.             je p1_found             ;Equal?
  692.             jl p1_less              ;Too low?
  693.  
  694. p1_greater: mov di,si               ;Set first half
  695.             mov si,cx
  696.             dec di
  697.             jmp p1_cont
  698.  
  699. p1_less:    mov di,dx               ;Set second half
  700.             inc si
  701.  
  702. p1_cont:    cmp cx,dx               ;Min = Max, done
  703.             je p1_nope
  704.             mov cx,si               ;Set limits
  705.             mov dx,di
  706.             jmp p1_loop             ;Loop back
  707.  
  708. p1_found:   xchg ax,si              ;AX = result
  709.  
  710. p1_done:    pop di si dx cx bx      ;Restore registers
  711.             pop bp                  ;Delete stack frame
  712.             ret 8                   ;Return
  713.  
  714. p1_nope:    mov ax,-1               ;Not found, return -1
  715.             jmp p1_done
  716.  
  717. EndP        lsearch
  718.  
  719. End
  720.  
  721. ~~~C_XSRCH
  722. Ideal
  723.  
  724. Public      xsearch
  725.  
  726. Model Tiny
  727. P186
  728. CodeSeg
  729.  
  730. ;****************** xsearch() -- Search sorted array, generalized
  731. ;int xsearch(void **ary, int size, void *elem, void *func);
  732.  
  733. ary         equ bp+10
  734. size        equ bp+8
  735. elem        equ bp+6
  736. func        equ bp+4
  737.  
  738. Proc        xsearch
  739.  
  740.             push bp                 ;Set up stack frame
  741.             mov bp,sp
  742.             push bx cx dx si di     ;Save registers
  743.  
  744.             mov bx,[ary]            ;BX = array
  745.             xor cx,cx               ;CX = lower limit
  746.             mov dx,[size]           ;DX = upper limit
  747.             dec dx
  748.  
  749. p3_loop:    mov si,cx               ;SI = middle element
  750.             add si,dx
  751.             shr si,1
  752.             add si,si
  753.             mov ax,[bx+si]          ;Get element
  754.             shr si,1                ;Fix SI
  755.             push ax [elem]          ;Check element
  756.             call [word func]
  757.             test ax,ax
  758.             je p3_found             ;Equal?
  759.             jl p3_less              ;Too low?
  760.  
  761. p3_greater: mov di,si               ;Set first half
  762.             mov si,cx
  763.             jmp p3_cont
  764.  
  765. p3_less:    mov di,dx               ;Set second half
  766.             inc si
  767.  
  768. p3_cont:    cmp cx,dx               ;Min = Max, done
  769.             je p3_nope
  770.             mov cx,si               ;Set limits
  771.             mov dx,di
  772.             jmp p3_loop             ;Loop back
  773.  
  774. p3_found:   xchg ax,si              ;AX = result
  775.  
  776. p3_done:    pop di si dx cx bx      ;Restore registers
  777.             pop bp                  ;Delete stack frame
  778.             ret 8                   ;Return
  779.  
  780. p3_nope:    mov ax,-1               ;Not found, return -1
  781.             jmp p3_done
  782.  
  783. EndP        xsearch
  784.  
  785. End
  786.  
  787. ~~~C_SSRCH
  788. Ideal
  789.  
  790. Extrn       strcmp:near
  791. Public      ssearch
  792.  
  793. Model Tiny
  794. P186
  795. CodeSeg
  796.  
  797. ;****************** ssearch() -- Search a sorted array of strings
  798. ;int ssearch(char **ary, int size, char *elem);
  799.  
  800. ary         equ bp+8
  801. size        equ bp+6
  802. elem        equ bp+4
  803.  
  804. Proc        ssearch
  805.  
  806.             push bp                 ;Set up stack frame
  807.             mov bp,sp
  808.             push bx cx dx si di     ;Save registers
  809.  
  810.             mov bx,[ary]            ;BX = array
  811.             xor cx,cx               ;CX = lower limit
  812.             mov dx,[size]           ;DX = upper limit
  813.             dec dx
  814.  
  815. p1_loop:    mov si,cx               ;SI = middle element
  816.             add si,dx
  817.             shr si,1
  818.             add si,si
  819.             mov ax,[bx+si]          ;Get element
  820.             shr si,1                ;Fix SI
  821.             push ax [elem]          ;Check element
  822.             call strcmp
  823.             test ax,ax
  824.             je p1_found             ;Equal?
  825.             jl p1_less              ;Too low?
  826.  
  827. p1_greater: mov di,si               ;Set first half
  828.             mov si,cx
  829.             jmp p1_cont
  830.  
  831. p1_less:    mov di,dx               ;Set second half
  832.             inc si
  833.  
  834. p1_cont:    cmp cx,dx               ;Min = Max, done
  835.             je p1_nope
  836.             mov cx,si               ;Set limits
  837.             mov dx,di
  838.             dec di
  839.             jmp p1_loop             ;Loop back
  840.  
  841. p1_found:   xchg ax,si              ;AX = result
  842.  
  843. p1_done:    pop di si dx cx bx      ;Restore registers
  844.             pop bp                  ;Delete stack frame
  845.             ret 6                   ;Return
  846.  
  847. p1_nope:    mov ax,-1               ;Not found, return -1
  848.             jmp p1_done
  849.  
  850. EndP        ssearch
  851.  
  852. End
  853.  
  854. ~~~C_ISORT
  855. Ideal
  856.  
  857. Public      isort
  858.  
  859. Model Tiny
  860. P186
  861. CodeSeg
  862.  
  863. ;****************** isort() -- Sort an array of integers
  864. ;void isort(int *ary, int size);
  865.  
  866. ary         equ bp+6
  867. max         equ bp+4
  868.  
  869. Proc        isort
  870.  
  871.             push bp                 ;Set up stack frame
  872.             mov bp,sp
  873.             pusha                   ;Save all registers
  874.  
  875.             mov bx,[ary]            ;Call recursive routine
  876.             xor cx,cx
  877.             mov dx,[max]
  878.             dec dx
  879.             add dx,dx
  880.             call p1_qsort
  881.  
  882.             popa                    ;Restore registers
  883.             pop bp                  ;Delete stack frame
  884.             ret 4                   ;Return
  885.  
  886. p1_qsort:   cmp cx,dx               ;One element, return
  887.             je p1_ret
  888.             pusha
  889.  
  890.             mov ax,dx               ;Two elements, sort them
  891.             sub ax,cx
  892.             cmp ax,2
  893.             jne p1_cont
  894.  
  895.             mov si,cx               ;SI, DI = low, high
  896.             mov di,dx
  897.  
  898.             mov ax,[bx+si]          ;Check them
  899.             cmp ax,[bx+di]
  900.             jle p1_done
  901.  
  902.             xchg ax,[bx+di]         ;Switch them
  903.             mov [bx+si],ax
  904.             jmp p1_done
  905.  
  906. p1_cont:    mov si,cx               ;AX = middle element
  907.             add si,dx
  908.             shr si,2
  909.             add si,si
  910.             mov ax,[bx+si]
  911.  
  912.             mov si,cx               ;SI = low, DI = high
  913.             mov di,dx
  914.  
  915. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  916.             jge p1_loop2            ; SI < DX, advance SI
  917.             cmp ax,[bx+si]
  918.             jle p1_loop2
  919.             inc si
  920.             inc si
  921.             jmp p1_loop
  922.  
  923. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  924.             jle p1_cont2            ; DI > CX, advance DI
  925.             cmp ax,[bx+di]
  926.             jge p1_cont2
  927.             dec di
  928.             dec di
  929.             jmp p1_loop2
  930.  
  931. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  932.             jge p1_rec
  933.  
  934.             push [bx+si]            ;Swap elements
  935.             push [bx+di]
  936.             pop [bx+si]
  937.             pop [bx+di]
  938.             inc si                  ;Advance SI, DI
  939.             inc si
  940.             dec di
  941.             dec di
  942.  
  943.             jmp p1_loop             ;Loop back
  944.  
  945. p1_rec:     cmp cx,si               ;If first half isn't empty,
  946.             je p1_skip1             ;recurse to sort it
  947.             xchg dx,di
  948.             call p1_qsort
  949.             xchg dx,di
  950.  
  951. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  952.             je p1_done              ;recurse to sort it
  953.             xchg cx,si
  954.             call p1_qsort
  955.             xchg cx,si
  956.  
  957. p1_done:    popa                    ;Restore registers
  958. p1_ret:     ret                     ;Return
  959.  
  960. EndP        isort
  961.  
  962. End
  963.  
  964. ~~~C_LSORT
  965. Ideal
  966.  
  967. Public      lsort
  968.  
  969. Model Tiny
  970. P186
  971. CodeSeg
  972.  
  973. ;****************** lsort() -- Sort an array of longs
  974. ;void lsort(long *ary, int size);
  975.  
  976. ary         equ bp+6
  977. max         equ bp+4
  978. num         equ bp-4
  979.  
  980. Proc        lsort
  981.  
  982.             enter 4,0               ;Set up stack frame
  983.             pusha                   ;Save all registers
  984.  
  985.             mov bx,[ary]            ;Call recursive routine
  986.             xor cx,cx
  987.             mov dx,[max]
  988.             dec dx
  989.             shl dx,2
  990.             call p1_qsort
  991.  
  992.             popa                    ;Restore registers
  993.             leave                   ;Delete stack frame
  994.             ret 4                   ;Return
  995.  
  996. p1_done:    popa                    ;Restore registers
  997. p1_ret:     ret                     ;Return
  998.  
  999. p1_qsort:   cmp cx,dx               ;One element, return
  1000.             je p1_ret
  1001.             pusha
  1002.  
  1003.             mov ax,dx               ;Two elements, sort them
  1004.             sub ax,cx
  1005.             cmp ax,4
  1006.             jne p1_cont
  1007.  
  1008.             mov si,cx               ;SI, DI = low, high
  1009.             mov di,dx
  1010.  
  1011.             mov dx,[bx+si+2]        ;Check them
  1012.             mov ax,[bx+si]
  1013.             cmp dx,[bx+di+2]
  1014.             jl p1_done
  1015.             jg p1_swap2
  1016.             cmp ax,[bx+di]
  1017.             jle p1_done
  1018.  
  1019. p1_swap2:   xchg ax,[bx+di]         ;Switch them
  1020.             mov [bx+si],ax
  1021.             xchg dx,[bx+di+2]
  1022.             mov [bx+si+2],dx
  1023.             jmp p1_done
  1024.  
  1025. p1_cont:    mov si,cx               ;NUM = middle element
  1026.             add si,dx
  1027.             shr si,3
  1028.             shl si,2
  1029.             mov ax,[bx+si]
  1030.             mov [num],ax
  1031.             mov ax,[bx+si+2]
  1032.             mov [num+2],ax
  1033.  
  1034.             mov si,cx               ;SI = low, DI = high
  1035.             mov di,dx
  1036.  
  1037. p1_loop:    cmp si,dx               ;While [BX+SI] < NUM and
  1038.             jge p1_loop2            ; SI < DX, advance SI
  1039.             mov ax,[num+2]
  1040.             cmp ax,[bx+si+2]
  1041.             jl p1_loop2
  1042.             jg p1_go1
  1043.             mov ax,[num]
  1044.             cmp ax,[bx+si]
  1045.             jle p1_loop2
  1046. p1_go1:     add si,4
  1047.             jmp p1_loop
  1048.  
  1049. p1_loop2:   cmp di,cx               ;While [BX+DI] > NUM and
  1050.             jle p1_cont2            ; DI > CX, advance DI
  1051.             mov ax,[num+2]
  1052.             cmp ax,[bx+di+2]
  1053.             jg p1_cont2
  1054.             jl p1_go2
  1055.             mov ax,[num]
  1056.             cmp ax,[bx+di]
  1057.             jge p1_cont2
  1058. p1_go2:     sub di,4
  1059.             jmp p1_loop2
  1060.  
  1061. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1062.             jge p1_rec
  1063.  
  1064.             push [bx+si]            ;Swap elements
  1065.             push [bx+di]
  1066.             pop [bx+si]
  1067.             pop [bx+di]
  1068.             push [bx+si+2]
  1069.             push [bx+di+2]
  1070.             pop [bx+si+2]
  1071.             pop [bx+di+2]
  1072.             add si,4                ;Advance SI, DI
  1073.             sub di,4
  1074.  
  1075.             jmp p1_loop             ;Loop back
  1076.  
  1077. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1078.             je p1_skip1             ;recurse to sort it
  1079.             xchg dx,di
  1080.             call p1_qsort
  1081.             xchg dx,di
  1082.  
  1083. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1084.             je p1_done2             ;recurse to sort it
  1085.             xchg cx,si
  1086.             call p1_qsort
  1087.             xchg cx,si
  1088.  
  1089. p1_done2:   jmp p1_done             ;Return
  1090.  
  1091. EndP        lsort
  1092.  
  1093. End
  1094.  
  1095. ~~~C_SSORT
  1096. Ideal
  1097.  
  1098. Extrn       strcmp:near
  1099. Public      ssort
  1100.  
  1101. Model Tiny
  1102. P186
  1103. CodeSeg
  1104.  
  1105. ;****************** ssort() -- Sort an array of strings
  1106. ;void ssort(char **ary, int size);
  1107.  
  1108. ary         equ bp+6
  1109. max         equ bp+4
  1110.  
  1111. Proc        ssort
  1112.  
  1113.             push bp                 ;Set up stack frame
  1114.             mov bp,sp
  1115.             pusha                   ;Save all registers
  1116.  
  1117.             mov bx,[ary]            ;Call recursive routine
  1118.             xor cx,cx
  1119.             mov dx,[max]
  1120.             dec dx
  1121.             add dx,dx
  1122.             call p1_qsort
  1123.  
  1124.             popa                    ;Restore registers
  1125.             pop bp                  ;Delete stack frame
  1126.             ret 4                   ;Return
  1127.  
  1128. p1_qsort:   cmp cx,dx               ;One element, return
  1129.             jne $+3
  1130.             ret
  1131.             pusha
  1132.  
  1133.             mov ax,dx               ;Two elements, sort them
  1134.             sub ax,cx
  1135.             cmp ax,2
  1136.             jne p1_cont
  1137.  
  1138.             mov si,cx               ;SI, DI = low, high
  1139.             mov di,dx
  1140.  
  1141.             mov ax,[bx+si]          ;Check them
  1142.             push ax [bx+di]
  1143.             call strcmp
  1144.             test ax,ax
  1145.             jle p1_done
  1146.  
  1147.             push [bx+si]            ;Switch them
  1148.             push [bx+di]
  1149.             pop [bx+si]
  1150.             pop [bx+di]
  1151.             jmp p1_done
  1152.  
  1153. p1_cont:    mov si,cx               ;AX = middle element
  1154.             add si,dx
  1155.             shr si,2
  1156.             add si,si
  1157.             mov ax,[bx+si]
  1158.  
  1159.             mov si,cx               ;SI = low, DI = high
  1160.             mov di,dx
  1161.  
  1162. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1163.             jge p1_loop2            ; SI < DX, advance SI
  1164.             push ax ax [bx+si]
  1165.             call strcmp
  1166.             pop ax
  1167.             jle p1_loop2
  1168.             inc si
  1169.             inc si
  1170.             jmp p1_loop
  1171.  
  1172. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1173.             jle p1_cont2            ; DI > CX, advance DI
  1174.             push ax ax [bx+di]
  1175.             call strcmp
  1176.             pop ax
  1177.             jge p1_cont2
  1178.             dec di
  1179.             dec di
  1180.             jmp p1_loop2
  1181.  
  1182. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1183.             jge p1_rec
  1184.  
  1185.             push [bx+si]            ;Swap elements
  1186.             push [bx+di]
  1187.             pop [bx+si]
  1188.             pop [bx+di]
  1189.             inc si                  ;Advance SI, DI
  1190.             inc si
  1191.             dec di
  1192.             dec di
  1193.  
  1194.             jmp p1_loop             ;Loop back
  1195.  
  1196. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1197.             je p1_skip1             ;recurse to sort it
  1198.             xchg dx,di
  1199.             call p1_qsort
  1200.             xchg dx,di
  1201.  
  1202. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1203.             je p1_done              ;recurse to sort it
  1204.             xchg cx,si
  1205.             call p1_qsort
  1206.             xchg cx,si
  1207.  
  1208. p1_done:    popa                    ;Restore registers
  1209. p1_ret:     ret                     ;Return
  1210.  
  1211. EndP        ssort
  1212.  
  1213. End
  1214.  
  1215. ~~~C_XSORT
  1216. Ideal
  1217.  
  1218. Public      xsort
  1219.  
  1220. Model Tiny
  1221. P186
  1222. CodeSeg
  1223.  
  1224. ;****************** xsort() -- Sort array, generalized
  1225. ;void xsort(void **ary, int size, void *func);
  1226.  
  1227. ary         equ bp+8
  1228. max         equ bp+6
  1229. func        equ bp+4
  1230.  
  1231. Proc        xsort
  1232.  
  1233.             push bp                 ;Set up stack frame
  1234.             mov bp,sp
  1235.             pusha                   ;Save all registers
  1236.  
  1237.             mov bx,[ary]            ;Call recursive routine
  1238.             xor cx,cx
  1239.             mov dx,[max]
  1240.             dec dx
  1241.             add dx,dx
  1242.             call p1_qsort
  1243.  
  1244.             popa                    ;Restore registers
  1245.             pop bp                  ;Delete stack frame
  1246.             ret 4                   ;Return
  1247.  
  1248. p1_qsort:   cmp cx,dx               ;One element, return
  1249.             jne $+3
  1250.             ret
  1251.             pusha
  1252.  
  1253.             mov ax,dx               ;Two elements, sort them
  1254.             sub ax,cx
  1255.             cmp ax,2
  1256.             jne p1_cont
  1257.  
  1258.             mov si,cx               ;SI, DI = low, high
  1259.             mov di,dx
  1260.  
  1261.             mov ax,[bx+si]          ;Check them
  1262.             push ax [bx+di]
  1263.             call [word func]
  1264.             test ax,ax
  1265.             jle p1_done
  1266.  
  1267.             push [bx+si]            ;Switch them
  1268.             push [bx+di]
  1269.             pop [bx+si]
  1270.             pop [bx+di]
  1271.             jmp p1_done
  1272.  
  1273. p1_cont:    mov si,cx               ;AX = middle element
  1274.             add si,dx
  1275.             shr si,2
  1276.             add si,si
  1277.             mov ax,[bx+si]
  1278.  
  1279.             mov si,cx               ;SI = low, DI = high
  1280.             mov di,dx
  1281.  
  1282. p1_loop:    cmp si,dx               ;While [BX+SI] < AX and
  1283.             jge p1_loop2            ; SI < DX, advance SI
  1284.             push ax ax [bx+si]
  1285.             call [word func]
  1286.             pop ax
  1287.             jle p1_loop2
  1288.             inc si
  1289.             inc si
  1290.             jmp p1_loop
  1291.  
  1292. p1_loop2:   cmp di,cx               ;While [BX+DI] > AX and
  1293.             jle p1_cont2            ; DI > CX, advance DI
  1294.             push ax ax [bx+di]
  1295.             call [word func]
  1296.             pop ax
  1297.             jge p1_cont2
  1298.             dec di
  1299.             dec di
  1300.             jmp p1_loop2
  1301.  
  1302. p1_cont2:   cmp si,di               ;Hit in middle, recurse
  1303.             jge p1_rec
  1304.  
  1305.             push [bx+si]            ;Swap elements
  1306.             push [bx+di]
  1307.             pop [bx+si]
  1308.             pop [bx+di]
  1309.             inc si                  ;Advance SI, DI
  1310.             inc si
  1311.             dec di
  1312.             dec di
  1313.  
  1314.             jmp p1_loop             ;Loop back
  1315.  
  1316. p1_rec:     cmp cx,si               ;If first half isn't empty,
  1317.             je p1_skip1             ;recurse to sort it
  1318.             xchg dx,di
  1319.             call p1_qsort
  1320.             xchg dx,di
  1321.  
  1322. p1_skip1:   cmp dx,di               ;If second half isn't empty,
  1323.             je p1_done              ;recurse to sort it
  1324.             xchg cx,si
  1325.             call p1_qsort
  1326.             xchg cx,si
  1327.  
  1328. p1_done:    popa                    ;Restore registers
  1329. p1_ret:     ret                     ;Return
  1330.  
  1331. EndP        xsort
  1332.  
  1333. End
  1334.  
  1335. ~~~C_LSHL
  1336. Ideal
  1337.  
  1338. Public      lshl
  1339.  
  1340. Model Tiny
  1341. CodeSeg
  1342. P186
  1343.  
  1344. ;****************** lshl() -- Shift long integer to the left
  1345. ;long lshl(long x, int d);    37 clocks (486)
  1346.  
  1347. x           equ bp+6
  1348. d           equ bp+4
  1349.  
  1350. Proc        lshl
  1351.  
  1352.             push bp                 ;Set up stack frame
  1353.             mov bp,sp
  1354.             push cx                 ;Save CX
  1355.  
  1356.             mov ax,[x]              ;DX:AX = x
  1357.             mov dx,[x+2]
  1358.             mov cl,[d]              ;CL = distance
  1359.  
  1360.             cmp cl,16               ;Distance > 16?
  1361.             jb p1_cont              ;Jump if not
  1362.  
  1363.             mov dx,ax               ;Shift left 16
  1364.             xor ax,ax
  1365.  
  1366. p1_cont:    and cl,15               ;Mask off high part
  1367.             push ax cx              ;Save AX, CX
  1368.             shl dx,cl               ;DX = (DX shl CL) +
  1369.             xor cl,15               ;     (AX shr (16 - CL))
  1370.             inc cx
  1371.             shr ax,cl
  1372.             add dx,ax
  1373.             pop cx ax               ;Restore AX, CX
  1374.             shl ax,cl               ;AX = AX shl CL
  1375.  
  1376.             pop cx                  ;Restore CX
  1377.             pop bp                  ;Delete stack frame
  1378.             ret 6                   ;Return
  1379.  
  1380. EndP        lshl
  1381.  
  1382. End
  1383.  
  1384. ~~~C_LSHR
  1385. Ideal
  1386.  
  1387. Public      lshr
  1388.  
  1389. Model Tiny
  1390. CodeSeg
  1391. P186
  1392.  
  1393. ;****************** lshr() -- Shift long integer to the right
  1394. ;long lshr(long x, int d);    37 clocks (486)
  1395.  
  1396. x           equ bp+6
  1397. d           equ bp+4
  1398.  
  1399. Proc        lshr
  1400.  
  1401.             push bp                 ;Set up stack frame
  1402.             mov bp,sp
  1403.             push cx                 ;Save CX
  1404.  
  1405.             mov ax,[x]              ;DX:AX = x
  1406.             mov dx,[x+2]
  1407.             mov cl,[d]              ;CL = distance
  1408.  
  1409.             cmp cl,16               ;Distance > 16?
  1410.             jb p1_cont              ;Jump if not
  1411.  
  1412.             mov ax,dx               ;Shift right 16
  1413.             xor dx,dx
  1414.  
  1415. p1_cont:    and cl,15               ;Mask off high part
  1416.             push dx cx              ;Save DX, CX
  1417.             shr ax,cl               ;AX = (AX shr CL) +
  1418.             xor cl,15               ;     (DX shl (16 - CL))
  1419.             inc cx
  1420.             shl dx,cl
  1421.             add ax,dx
  1422.             pop cx dx               ;Restore DX, CX
  1423.             shr dx,cl               ;DX = DX shr CL
  1424.  
  1425.             pop cx                  ;Restore CX
  1426.             pop bp                  ;Delete stack frame
  1427.             ret 6                   ;Return
  1428.  
  1429. EndP        lshr
  1430.  
  1431. End
  1432.  
  1433. ~~~C_LSAR
  1434. Ideal
  1435.  
  1436. Public      lsar
  1437.  
  1438. Model Tiny
  1439. CodeSeg
  1440. P186
  1441.  
  1442. ;****************** lsar() -- Shift long integer to the right, signed
  1443. ;long lsar(long x, int d);    39 clocks (486)
  1444.  
  1445. x           equ bp+6
  1446. d           equ bp+4
  1447.  
  1448. Proc        lsar
  1449.  
  1450.             push bp                 ;Set up stack frame
  1451.             mov bp,sp
  1452.             push cx                 ;Save CX
  1453.  
  1454.             mov ax,[x]              ;DX:AX = x
  1455.             mov dx,[x+2]
  1456.             mov cl,[d]              ;CL = distance
  1457.  
  1458.             cmp cl,16               ;Distance > 16?
  1459.             jb p1_cont              ;Jump if not
  1460.  
  1461.             mov ax,dx               ;Shift right 16
  1462.             cbw
  1463.  
  1464. p1_cont:    and cl,15               ;Mask off high part
  1465.             push dx cx              ;Save DX, CX
  1466.             shr ax,cl               ;AX = (AX shr CL) +
  1467.             xor cl,15               ;     (DX shl (16 - CL))
  1468.             inc cx
  1469.             shl dx,cl
  1470.             add ax,dx
  1471.             pop cx dx               ;Restore DX, CX
  1472.             sar dx,cl               ;DX = DX sar CL
  1473.  
  1474.             pop cx                  ;Restore CX
  1475.             pop bp                  ;Delete stack frame
  1476.             ret 6                   ;Return
  1477.  
  1478. EndP        lsar
  1479.  
  1480. End
  1481.  
  1482. ~~~C_LMUL
  1483. Ideal
  1484.  
  1485. Public      lmul
  1486.  
  1487. Model Tiny
  1488. CodeSeg
  1489. P186
  1490.  
  1491. ;****************** lmul() -- Multiply long integers
  1492. ;long lmul(long x, long y);   70 clocks (486)
  1493.  
  1494. x           equ bp+8
  1495. y           equ bp+4
  1496.  
  1497. Proc        lmul
  1498.  
  1499.             push bp                 ;Set up stack frame
  1500.             mov bp,sp
  1501.             push bx                 ;Save registers
  1502.  
  1503.             mov ax,[x]              ;Multiply low words
  1504.             mul [word y]
  1505.             mov bx,dx               ;BX = high word
  1506.             push ax                 ;Save low word
  1507.  
  1508.             mov ax,[x+2]            ;Multiply high by low Y
  1509.             mul [word y]
  1510.             add bx,ax               ;Add in result
  1511.  
  1512.             mov ax,[y+2]            ;Multiply high by low X
  1513.             mul [word x]
  1514.             add ax,bx               ;Add in result
  1515.  
  1516.             pop dx                  ;Restore low word
  1517.             xchg dx,ax              ;DX:AX = result
  1518.  
  1519.             pop bx                  ;Restore registers
  1520.             pop bp                  ;Delete stack frame
  1521.             ret 8                   ;Return
  1522.  
  1523. EndP        lmul
  1524.  
  1525. End
  1526.  
  1527. ~~~C_LIMUL
  1528. Ideal
  1529.  
  1530. Public      limul
  1531.  
  1532. Model Tiny
  1533. CodeSeg
  1534. P186
  1535.  
  1536. ;****************** limul() -- Multiply long integers, signed
  1537. ;long limul(long x, long y);   89-97 clocks (486)
  1538.  
  1539. x           equ bp+8
  1540. y           equ bp+4
  1541.  
  1542. Proc        limul
  1543.  
  1544.             push bp                 ;Set up stack frame
  1545.             mov bp,sp
  1546.             push bx cx              ;Save registers
  1547.  
  1548.             xor cx,cx               ;Clear neg flag
  1549.  
  1550.             mov ax,[x+2]            ;AX = x high word
  1551.             test ax,ax              ;Negative?
  1552.             jge p1_xok
  1553.             neg ax                  ;Negate X
  1554.             neg [word x]
  1555.             sbb ax,0
  1556.             not cx                  ;Set neg flag
  1557.  
  1558. p1_xok:     mov [x+2],ax            ;Save X
  1559.  
  1560.             mov ax,[y+2]            ;AX = y high word
  1561.             test ax,ax              ;Negative?
  1562.             jge p1_yok
  1563.             neg ax                  ;Negate Y
  1564.             neg [word y]
  1565.             sbb ax,0
  1566.             not cx                  ;Flip neg flag
  1567.  
  1568. p1_yok:     mov [y+2],ax            ;Save Y
  1569.  
  1570.             mov ax,[x]              ;Multiply low words
  1571.             mul [word y]
  1572.             mov bx,dx               ;BX = high word
  1573.             push ax                 ;Save low word
  1574.  
  1575.             mov ax,[x+2]            ;Multiply high by low Y
  1576.             mul [word y]
  1577.             add bx,ax               ;Add in result
  1578.  
  1579.             mov ax,[y+2]            ;Multiply high by low X
  1580.             mul [word x]
  1581.             add ax,bx               ;Add in result
  1582.  
  1583.             pop dx                  ;Restore low word
  1584.             xchg dx,ax              ;DX:AX = result
  1585.  
  1586.             test cx,cx              ;Check neg flag
  1587.             jz p1_done
  1588.  
  1589.             neg dx                  ;Negate result
  1590.             neg ax
  1591.             sbb dx,0
  1592.  
  1593. p1_done:    pop cx bx               ;Restore registers
  1594.             pop bp                  ;Delete stack frame
  1595.             ret 8                   ;Return
  1596.  
  1597. EndP        limul
  1598.  
  1599. End
  1600.  
  1601. ~~~C_LDIV
  1602. Ideal
  1603.  
  1604. Public      ldiv
  1605.  
  1606. Model Tiny
  1607. CodeSeg
  1608. P186
  1609.  
  1610. ;****************** ldiv() -- Divide long integers
  1611. ;long ldiv(long x, long y);   692-948 clocks (486)
  1612.  
  1613. x           equ bp+8
  1614. y           equ bp+4
  1615.  
  1616. Proc        ldiv
  1617.  
  1618.             push bp                 ;Set up stack frame
  1619.             mov bp,sp
  1620.             push bx cx si           ;Save registers
  1621.  
  1622.             xor ax,ax               ;Clear DX:AX, CX:BX
  1623.             xor bx,bx               ;DX:AX will contain
  1624.             xor cx,cx               ;the result, and
  1625.             xor dx,dx               ;CX:BX will be X.
  1626.             mov si,32               ;SI = count
  1627.  
  1628. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1629.             rcl [word x+2],1
  1630.             adc bx,bx
  1631.             adc cx,cx
  1632.  
  1633.             add ax,ax               ;Shift result left by 1
  1634.             adc dx,dx
  1635.  
  1636.             cmp cx,[y+2]            ;Compare the partial X
  1637.             jb p1_skip              ;to Y, if X is bigger
  1638.             ja p1_sub               ;then Y is subtracted
  1639.             cmp bx,[y]              ;from the partial X.
  1640.             jb p1_skip
  1641.  
  1642. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1643.             sbb cx,[y+2]
  1644.             add ax,1                ;Add one bit to result
  1645.             adc dx,0
  1646.  
  1647. p1_skip:    dec si                  ;Loop back
  1648.             jnz p1_loop
  1649.  
  1650.             pop si cx bx            ;Restore registers
  1651.             pop bp                  ;Delete stack frame
  1652.             ret 8                   ;Return
  1653.  
  1654. EndP        ldiv
  1655.  
  1656. End
  1657.  
  1658. ~~~C_LIDIV
  1659. Ideal
  1660.  
  1661. Public      lidiv
  1662.  
  1663. Model Tiny
  1664. CodeSeg
  1665. P186
  1666.  
  1667. ;****************** lidiv() -- Divide long integers, signed
  1668. ;long lidiv(long x, long y);   711-975 clocks (486)
  1669.  
  1670. x           equ bp+8
  1671. y           equ bp+4
  1672.  
  1673. Proc        lidiv
  1674.  
  1675.             push bp                 ;Set up stack frame
  1676.             mov bp,sp
  1677.             push bx cx si           ;Save registers
  1678.  
  1679.             xor cx,cx               ;Clear neg flag
  1680.  
  1681.             mov ax,[x+2]            ;AX = x high word
  1682.             test ax,ax              ;Negative?
  1683.             jge p1_xok
  1684.             neg ax                  ;Negate X
  1685.             neg [word x]
  1686.             sbb ax,0
  1687.             not cx                  ;Set neg flag
  1688.  
  1689. p1_xok:     mov [x+2],ax            ;Save X
  1690.  
  1691.             mov ax,[y+2]            ;AX = y high word
  1692.             test ax,ax              ;Negative?
  1693.             jge p1_yok
  1694.             neg ax                  ;Negate Y
  1695.             neg [word y]
  1696.             sbb ax,0
  1697.             not cx                  ;Flip neg flag
  1698.  
  1699. p1_yok:     mov [y+2],ax            ;Save Y
  1700.             push cx                 ;Save neg flag
  1701.  
  1702.             xor ax,ax               ;Clear DX:AX, CX:BX
  1703.             xor bx,bx               ;DX:AX will contain
  1704.             xor cx,cx               ;the result, and
  1705.             xor dx,dx               ;CX:BX will be X.
  1706.             mov si,32               ;SI = count
  1707.  
  1708. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1709.             rcl [word x+2],1
  1710.             adc bx,bx
  1711.             adc cx,cx
  1712.  
  1713.             add ax,ax               ;Shift result left by 1
  1714.             adc dx,dx
  1715.  
  1716.             cmp cx,[y+2]            ;Compare the partial X
  1717.             jb p1_skip              ;to Y, if X is bigger
  1718.             ja p1_sub               ;then Y is subtracted
  1719.             cmp bx,[y]              ;from the partial X.
  1720.             jb p1_skip
  1721.  
  1722. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1723.             sbb cx,[y+2]
  1724.             add ax,1                ;Add one bit to result
  1725.             adc dx,0
  1726.  
  1727. p1_skip:    dec si                  ;Loop back
  1728.             jnz p1_loop
  1729.  
  1730.             pop cx                  ;Restore neg flag
  1731.             test cx,cx              ;Check neg flag
  1732.             jz p1_done
  1733.  
  1734.             neg dx                  ;Negate result
  1735.             neg ax
  1736.             sbb dx,0
  1737.  
  1738. p1_done:    pop si cx bx            ;Restore registers
  1739.             pop bp                  ;Delete stack frame
  1740.             ret 8                   ;Return
  1741.  
  1742. EndP        lidiv
  1743.  
  1744. End
  1745.  
  1746. ~~~C_LMOD
  1747. Ideal
  1748.  
  1749. Extrn       ldiv:near,lmul:near
  1750. Public      lmod
  1751.  
  1752. Model Tiny
  1753. CodeSeg
  1754. P186
  1755.  
  1756. ;****************** lmod() -- Modulo on long integers
  1757. ;long lmod(long x, long y);
  1758.  
  1759. x           equ bp+8
  1760. y           equ bp+4
  1761.  
  1762. Proc        lmod
  1763.  
  1764.             push bp                 ;Set up stack frame
  1765.             mov bp,sp
  1766.  
  1767.             push [x] [x+2]          ;x MOD y = x - (x / y) * y
  1768.             push [y] [y+2]
  1769.             call ldiv
  1770.             push [y] [y+2]
  1771.             push dx ax
  1772.             call lmul
  1773.  
  1774.             neg dx                  ;Negate, add in X
  1775.             neg ax
  1776.             sbb dx,0
  1777.             add ax,[x]
  1778.             adc dx,[x+2]
  1779.  
  1780.             pop bp                  ;Delete stack frame
  1781.             ret 8                   ;Return
  1782.  
  1783. EndP        lmod
  1784.  
  1785. End
  1786.  
  1787. ~~~C_LIMOD
  1788. Ideal
  1789.  
  1790. Extrn       lidiv:near,limul:near
  1791. Public      limod
  1792.  
  1793. Model Tiny
  1794. CodeSeg
  1795. P186
  1796.  
  1797. ;****************** limod() -- Modulo on long integers, signed
  1798. ;long limod(long x, long y);
  1799.  
  1800. x           equ bp+8
  1801. y           equ bp+4
  1802.  
  1803. Proc        limod
  1804.  
  1805.             push bp                 ;Set up stack frame
  1806.             mov bp,sp
  1807.  
  1808.             push [x] [x+2]          ;x MOD y = x - (x / y) * y
  1809.             push [y] [y+2]
  1810.             call lidiv
  1811.             push [y] [y+2]
  1812.             push dx ax
  1813.             call limul
  1814.  
  1815.             neg dx                  ;Negate, add in X
  1816.             neg ax
  1817.             sbb dx,0
  1818.             add ax,[x]
  1819.             adc dx,[x+2]
  1820.  
  1821.             pop bp                  ;Delete stack frame
  1822.             ret 8                   ;Return
  1823.  
  1824. EndP        limod
  1825.  
  1826. End
  1827.  
  1828. ~~~C_FIXMUL
  1829. Ideal
  1830.  
  1831. Public      fixmul
  1832.  
  1833. Model Tiny
  1834. CodeSeg
  1835. P186
  1836.  
  1837. ;****************** fixmul() -- Multiply fixed point numbers
  1838. ;long fixmul(long x, long y);   101-109 clocks (486)
  1839.  
  1840. x           equ bp+8
  1841. y           equ bp+4
  1842.  
  1843. Proc        fixmul
  1844.  
  1845.             push bp                 ;Set up stack frame
  1846.             mov bp,sp
  1847.             push bx cx si           ;Save registers
  1848.  
  1849.             xor si,si               ;Clear neg flag
  1850.  
  1851.             mov ax,[x+2]            ;AX = x high word
  1852.             test ax,ax              ;Negative?
  1853.             jge p1_xok
  1854.             neg ax                  ;Negate X
  1855.             neg [word x]
  1856.             sbb ax,0
  1857.             not si                  ;Set neg flag
  1858.  
  1859. p1_xok:     mov [x+2],ax            ;Save X
  1860.  
  1861.             mov ax,[y+2]            ;AX = y high word
  1862.             test ax,ax              ;Negative?
  1863.             jge p1_yok
  1864.             neg ax                  ;Negate Y
  1865.             neg [word y]
  1866.             sbb ax,0
  1867.             not si                  ;Flip neg flag
  1868.  
  1869. p1_yok:     mov [y+2],ax            ;Save Y
  1870.  
  1871.             mov ax,[x+2]            ;Multiply high by low Y
  1872.             mul [word y]
  1873.             mov cx,dx               ;Save in CX:BX
  1874.             xchg bx,ax
  1875.  
  1876.             mov ax,[y+2]            ;Multiply high by low X
  1877.             mul [word x]
  1878.             add bx,ax               ;Add in result
  1879.             adc cx,dx
  1880.  
  1881.             mov ax,[x]              ;Multiply low words
  1882.             mul [word y]
  1883.             add bx,dx               ;Add in result
  1884.             adc cx,0
  1885.  
  1886.             mov ax,[x+2]            ;Multiply high words
  1887.             mul [word y+2]
  1888.             add ax,cx               ;Add in result
  1889.             mov dx,bx               ;DX:AX = result
  1890.             xchg dx,ax
  1891.  
  1892.             test si,si              ;Check neg flag
  1893.             jz p1_done
  1894.  
  1895.             neg dx                  ;Negate result
  1896.             neg ax
  1897.             sbb dx,0
  1898.  
  1899. p1_done:    pop si cx bx            ;Restore registers
  1900.             pop bp                  ;Delete stack frame
  1901.             ret 8                   ;Return
  1902.  
  1903. EndP        fixmul
  1904.  
  1905. End
  1906.  
  1907. ~~~C_FIXDIV
  1908. Ideal
  1909.  
  1910. Public      fixdiv
  1911.  
  1912. Model Tiny
  1913. CodeSeg
  1914. P186
  1915.  
  1916. ;****************** fixdiv() -- Divide fixed point numbers
  1917. ;long fixdiv(long x, long y);   1028-1412 clocks (486)
  1918.  
  1919. x           equ bp+8
  1920. y           equ bp+4
  1921.  
  1922. Proc        fixdiv
  1923.  
  1924.             push bp                 ;Set up stack frame
  1925.             mov bp,sp
  1926.             push bx cx si           ;Save registers
  1927.  
  1928.             xor cx,cx               ;Clear neg flag
  1929.  
  1930.             mov ax,[x+2]            ;AX = x high word
  1931.             test ax,ax              ;Negative?
  1932.             jge p1_xok
  1933.             neg ax                  ;Negate X
  1934.             neg [word x]
  1935.             sbb ax,0
  1936.             not cx                  ;Set neg flag
  1937.  
  1938. p1_xok:     mov [x+2],ax            ;Save X
  1939.  
  1940.             mov ax,[y+2]            ;AX = y high word
  1941.             test ax,ax              ;Negative?
  1942.             jge p1_yok
  1943.             neg ax                  ;Negate Y
  1944.             neg [word y]
  1945.             sbb ax,0
  1946.             not cx                  ;Flip neg flag
  1947.  
  1948. p1_yok:     mov [y+2],ax            ;Save Y
  1949.             push cx                 ;Save neg flag
  1950.  
  1951.             xor ax,ax               ;Clear DX:AX, CX:BX
  1952.             xor bx,bx               ;DX:AX will contain
  1953.             xor cx,cx               ;the result, and
  1954.             xor dx,dx               ;CX:BX will be X.
  1955.             mov si,48               ;SI = count
  1956.  
  1957. p1_loop:    shl [word x],1          ;Shift in one bit of X
  1958.             rcl [word x+2],1
  1959.             adc bx,bx
  1960.             adc cx,cx
  1961.  
  1962.             add ax,ax               ;Shift result left by 1
  1963.             adc dx,dx
  1964.  
  1965.             cmp cx,[y+2]            ;Compare the partial X
  1966.             jb p1_skip              ;to Y, if X is bigger
  1967.             ja p1_sub               ;then Y is subtracted
  1968.             cmp bx,[y]              ;from the partial X.
  1969.             jb p1_skip
  1970.  
  1971. p1_sub:     sub bx,[y]              ;Subtract Y from partial X
  1972.             sbb cx,[y+2]
  1973.             add ax,1                ;Add one bit to result
  1974.             adc dx,0
  1975.  
  1976. p1_skip:    dec si                  ;Loop back
  1977.             jnz p1_loop
  1978.  
  1979.             pop cx                  ;Restore neg flag
  1980.             test cx,cx              ;Check neg flag
  1981.             jz p1_done
  1982.  
  1983.             neg dx                  ;Negate result
  1984.             neg ax
  1985.             sbb dx,0
  1986.  
  1987. p1_done:    pop si cx bx            ;Restore registers
  1988.             pop bp                  ;Delete stack frame
  1989.             ret 8                   ;Return
  1990.  
  1991. EndP        fixdiv
  1992.  
  1993. End
  1994.  
  1995. ~~~C_TRIG
  1996. Ideal
  1997.  
  1998. Extrn       fixmul:near, fixdiv:near
  1999. Public      sine, cosine, tangent, cotangent
  2000. Public      secant, cosecant
  2001.  
  2002. Model Tiny
  2003. CodeSeg
  2004. P186
  2005.  
  2006. ;****************** TaylorSine() -- Calculate sine by Taylor series
  2007. ;long TaylorSine(long x);
  2008.  
  2009. ; *──────────────────────────────────────────────────*
  2010. ; │               x^3     x^5     x^7     x^9        │
  2011. ; │ sin(x) = x - ───── + ───── - ───── + ───── - ... │
  2012. ; │               3 !     5 !     7 !     9 !        │
  2013. ; *──────────────────────────────────────────────────*
  2014.  
  2015. x           equ bp+4
  2016.  
  2017. Proc        TaylorSine
  2018.  
  2019.             enter 2,0               ;Set up stack frame
  2020.             push bx cx si di        ;Save registers
  2021.  
  2022.             mov dx,[x+2]            ;First term = x
  2023.             mov ax,[x]
  2024.             xor cx,cx               ;Result = 0
  2025.             xor bx,bx
  2026.             mov [word bp-2],1       ;Count = 1
  2027.  
  2028. TS_loop:    add bx,ax               ;Add in term
  2029.             adc cx,dx
  2030.  
  2031.             mov si,[x]              ;DI:SI = x
  2032.             mov di,[x+2]
  2033.             push dx ax di si        ;term = last-term * x
  2034.             call fixmul
  2035.             push dx ax di si        ;term = last-term * x^2
  2036.             call fixmul
  2037.  
  2038.             mov di,dx               ;DI:SI = term
  2039.             xchg si,ax
  2040.             add [word bp-2],2       ;n = n + 2
  2041.             mov ax,[bp-2]           ;AX = n
  2042.             mov dx,[bp-2]           ;DX = n - 1
  2043.             dec dx
  2044.             mul dx                  ;AX = n * (n - 1)
  2045.             push di si ax 0         ;term = last-term * x^2 / n(n-1)
  2046.             call fixdiv             ;the next term in the series
  2047.  
  2048.             neg dx                  ;Invert sign
  2049.             neg ax
  2050.             sbb dx,0
  2051.  
  2052.             test ax,ax              ;Loop while not zero
  2053.             jnz TS_loop
  2054.             test dx,dx
  2055.             jnz TS_loop
  2056.  
  2057.             xchg ax,bx              ;Result in DX:AX
  2058.             mov dx,cx
  2059.  
  2060.             pop di si cx bx         ;Restore registers
  2061.             leave                   ;Delete stack frame
  2062.             ret 4                   ;Return
  2063.  
  2064. EndP        TaylorSine
  2065.  
  2066. Pi          dd 0003243Fh            ;Pi   (3.243F6A88... hex)
  2067. TwoPi       dd 0006487Fh            ;Pi*2 (6.487ED511... hex)
  2068. HalfPi      dd 00019220h            ;Pi/2 (1.921FB544... hex)
  2069.  
  2070. ;****************** sine() -- Trigonometric sine function
  2071. ;long sine(long x);
  2072.  
  2073. x           equ bp+4
  2074.  
  2075. Proc        sine
  2076.  
  2077.             push bp                 ;Set up stack frame
  2078.             mov bp,sp
  2079.  
  2080.             mov dx,[x+2]            ;DX:AX = x
  2081.             mov ax,[x]
  2082.             add ax,[word Pi]        ; x + Pi
  2083.             adc dx,[word Pi+2]
  2084.             push dx ax              ;Divide by 2*Pi
  2085.             push [word TwoPi+2]
  2086.             push [word TwoPi]
  2087.             call fixdiv
  2088.  
  2089.             xor ax,ax               ;Convert to integer
  2090.             push dx ax              ;Multiply by 2*Pi
  2091.             push [word TwoPi+2]
  2092.             push [word TwoPi]
  2093.             call fixmul
  2094.  
  2095.             neg dx                  ;Negate...
  2096.             neg ax
  2097.             sbb dx,0
  2098.             add ax,[x]              ;Add in X
  2099.             adc dx,[x+2]
  2100.  
  2101.             push dx ax              ;Calculate sine
  2102.             call TaylorSine
  2103.  
  2104.             pop bp                  ;Delete stack frame
  2105.             ret 4                   ;Return
  2106.  
  2107. EndP        sine
  2108.  
  2109. ;****************** cosine() -- Trigonometric cosine function
  2110. ;long cosine(long x);
  2111.  
  2112. x           equ bp+4
  2113.  
  2114. Proc        cosine
  2115.  
  2116.             push bp                 ;Set up stack frame
  2117.             mov bp,sp
  2118.  
  2119.             mov dx,[x+2]            ;DX:AX = x
  2120.             mov ax,[x]
  2121.             add ax,[word HalfPi]    ; x + Pi+2
  2122.             adc dx,[word HalfPi+2]
  2123.             push dx ax              ;cos(x) = sin(x + Pi/4)
  2124.             call sine
  2125.  
  2126.             pop bp                  ;Delete stack frame
  2127.             ret 4                   ;Return
  2128.  
  2129. EndP        cosine
  2130.  
  2131. ;****************** tangent() -- Trigonometric tangent function
  2132. ;long tangent(long x);
  2133.  
  2134. x           equ bp+4
  2135.  
  2136. Proc        tangent
  2137.  
  2138.             push bp                 ;Set up stack frame
  2139.             mov bp,sp
  2140.             push bx cx              ;Save registers
  2141.  
  2142.             push [x+2] [x]          ;CX:BX = sin(x)
  2143.             call sine
  2144.             mov cx,dx
  2145.             xchg bx,ax
  2146.             push [x+2] [x]          ;DX:AX = cos(x)
  2147.             call cosine
  2148.             push cx bx dx ax        ;tan(x) = sin(x) / cos(x)
  2149.             call fixdiv
  2150.  
  2151.             pop cx bx               ;Restore registers
  2152.             pop bp                  ;Delete stack frame
  2153.             ret 4                   ;Return
  2154.  
  2155. EndP        tangent
  2156.  
  2157. ;****************** cotangent() -- Trigonometric cotangent function
  2158. ;long cotangent(long x);
  2159.  
  2160. x           equ bp+4
  2161.  
  2162. Proc        cotangent
  2163.  
  2164.             push bp                 ;Set up stack frame
  2165.             mov bp,sp
  2166.             push bx cx              ;Save registers
  2167.  
  2168.             push [x+2] [x]          ;CX:BX = sin(x)
  2169.             call sine
  2170.             mov cx,dx
  2171.             xchg bx,ax
  2172.             push [x+2] [x]          ;DX:AX = cos(x)
  2173.             call cosine
  2174.             push dx ax cx bx        ;cot(x) = cos(x) / sin(x)
  2175.             call fixdiv
  2176.  
  2177.             pop cx bx               ;Restore registers
  2178.             pop bp                  ;Delete stack frame
  2179.             ret 4                   ;Return
  2180.  
  2181. EndP        cotangent
  2182.  
  2183. ;****************** secant() -- Trigonometric secant function
  2184. ;long secant(long x);
  2185.  
  2186. x           equ bp+4
  2187.  
  2188. Proc        secant
  2189.  
  2190.             push bp                 ;Set up stack frame
  2191.             mov bp,sp
  2192.  
  2193.             push [x+2] [x]          ;DX:AX = cos(x)
  2194.             call cosine
  2195.             push 1 0 dx ax          ;sec(x) = 1 / cos(x)
  2196.             call fixdiv
  2197.  
  2198.             pop bp                  ;Delete stack frame
  2199.             ret 4                   ;Return
  2200.  
  2201. EndP        secant
  2202.  
  2203. ;****************** cosecant() -- Trigonometric cosecant function
  2204. ;long cosecant(long x);
  2205.  
  2206. x           equ bp+4
  2207.  
  2208. Proc        cosecant
  2209.  
  2210.             push bp                 ;Set up stack frame
  2211.             mov bp,sp
  2212.  
  2213.             push [x+2] [x]          ;DX:AX = cos(x)
  2214.             call sine
  2215.             push 1 0 dx ax          ;csc(x) = 1 / sin(x)
  2216.             call fixdiv
  2217.  
  2218.             pop bp                  ;Delete stack frame
  2219.             ret 4                   ;Return
  2220.  
  2221. EndP        cosecant
  2222.  
  2223. End
  2224.  
  2225. ~~~C_FIXTOA
  2226. Ideal
  2227.  
  2228. Public      fixtoa
  2229.  
  2230. Model Tiny
  2231. CodeSeg
  2232. P186
  2233.  
  2234. ;****************** fixtoa() -- Convert fixed point number to string
  2235. ;void fixtoa(int n, char *strp);
  2236.  
  2237. n           equ bp+6
  2238. strp        equ bp+4
  2239.  
  2240. Proc        fixtoa
  2241.  
  2242.             push bp                 ;Set up stack frame
  2243.             mov bp,sp
  2244.             pusha                   ;Save all registers
  2245.  
  2246.             mov di,[strp]           ;DI = string pointer
  2247.             mov dx,[n+2]            ;DX:AX = n
  2248.             mov ax,[n]
  2249.  
  2250.             test dx,dx              ;Negative?
  2251.             jge p1_noneg
  2252.             mov [byte di],'-'       ;Store minus sign
  2253.             inc di
  2254.             neg dx                  ;Make it positive
  2255.             neg ax
  2256.             sbb dx,0
  2257.  
  2258. p1_noneg:   push dx                 ;Save DX
  2259.             xor bx,bx               ;Zero rem flag
  2260.             add ax,ax               ;Shift out high bit
  2261.             adc bx,0                ;BX = rem flag
  2262.             shr ax,1                ;Restore AX
  2263.  
  2264.             mov cx,50000            ;AX = AX * 50000
  2265.             mul cx
  2266.             shr ax,15               ;AX = AX / 32768
  2267.             shl dx,1
  2268.             or ax,dx
  2269.             pop dx                  ;Restore DX
  2270.             push bx ax              ;Save BX, AX
  2271.  
  2272.             xchg dx,ax              ;Integer part in AX
  2273.  
  2274.             xor cx,cx               ;Zero CX
  2275.             mov si,10               ;SI = 10
  2276.  
  2277. p1_dloop:   xor dx,dx               ;Divide by 10
  2278.             div si
  2279.             mov bl,dl               ;Remainder in BL
  2280.             add bl,30h              ;Convert to digit
  2281.             push bx                 ;Push digit
  2282.             inc cx
  2283.             test ax,ax              ;Loop back
  2284.             jnz p1_dloop
  2285.  
  2286. p1_ploop:   pop ax                  ;Pop digit
  2287.             mov [di],al             ;Store digit
  2288.             inc di
  2289.             loop p1_ploop           ;Loop back
  2290.  
  2291.             mov [byte di],'.'       ;Store decimal point
  2292.             inc di
  2293.             pop ax bx               ;Restore low data
  2294.             xor dx,dx               ;Zero DX
  2295.             test bx,bx              ;Check for high part
  2296.             jz p1_nohigh
  2297.  
  2298.             add ax,50000            ;Add in 50000
  2299.             adc dx,0
  2300.  
  2301. p1_nohigh:  mov si,10               ;SI = 10
  2302.             mov cx,5                ;5 digits
  2303.             jmp p1_skip1
  2304.  
  2305. p1_dloopb:  xor dx,dx               ;Zero DX
  2306. p1_skip1:   div si                  ;Divide by 10
  2307.             mov bl,dl               ;Remainder in BL
  2308.             add bl,30h              ;Convert to digit
  2309.             push bx                 ;Push digit
  2310.             loop p1_dloopb          ;Loop back
  2311.  
  2312.             mov cx,5                ;5 digits
  2313.  
  2314. p1_ploopb:  pop ax                  ;Pop digit
  2315.             mov [di],al             ;Store digit
  2316.             inc di
  2317.             loop p1_ploopb          ;Loop back
  2318.  
  2319.             mov [byte di],0         ;Add the null byte
  2320.  
  2321. p1_done:    popa                    ;Restore registers
  2322.             pop bp                  ;Delete stack frame
  2323.             ret 6                   ;Return
  2324.  
  2325. EndP        fixtoa
  2326.  
  2327. End
  2328.  
  2329. ~~~C_ATOFIX
  2330. Ideal
  2331.  
  2332. Public      atofix
  2333.  
  2334. Model Tiny
  2335. CodeSeg
  2336. P186
  2337.  
  2338. ;****************** atofix() -- Convert string to fixed point number
  2339. ;long atofix(char *strp);
  2340.  
  2341. strp        equ bp+4
  2342.  
  2343. Proc        atofix
  2344.  
  2345.             push bp                 ;Set up stack frame
  2346.             mov bp,sp
  2347.             push bx cx si di bp     ;Save registers
  2348.  
  2349.             mov si,[strp]           ;SI = string
  2350.  
  2351.             xor ax,ax               ;AX = 0
  2352.             xor bh,bh               ;BH = 0
  2353.             mov cx,10               ;CX = 10
  2354.  
  2355. p1_ploop:   mov bl,[si]             ;Load char
  2356.             inc si
  2357.             cmp bl,' '              ;Loop while char is space
  2358.             je p1_ploop             ;(20h, or 09h thru 0Dh)
  2359.             cmp bl,9
  2360.             jna p1_go
  2361.             cmp bl,13
  2362.             jbe p1_ploop
  2363.  
  2364. p1_go:      xor bp,bp               ;BP = 0
  2365.             cmp bl,'+'              ;If char = '+', ignore
  2366.             je p1_loop
  2367.             cmp bl,'-'              ;If char <> '-', keep it
  2368.             jne p1_skip
  2369.             inc bp                  ;Set negative flag
  2370.  
  2371. p1_loop:    mov bl,[si]             ;Load char
  2372.             inc si
  2373.  
  2374. p1_skip:    xor dx,dx               ;Clear DX
  2375.             cmp bl,'.'              ;Decimal point, continue
  2376.             je p1_cont
  2377.             cmp bl,'9'              ;Not a digit, finish
  2378.             ja p1_finish
  2379.             sub bl,'0'
  2380.             jc p1_finish
  2381.  
  2382.             mul cx                  ;Multiply by 10
  2383.             add ax,bx               ;Add in digit...
  2384.             jmp p1_loop             ;Loop back
  2385.  
  2386. p1_cont:    push ax                 ;Save integer part
  2387.             xor ax,ax               ;Zero AX
  2388.             mov di,1                ;DI = 1
  2389.  
  2390. p1_floop:   mov bl,[si]             ;Load char
  2391.             inc si
  2392.  
  2393.             cmp bl,'9'              ;Not a digit, finish
  2394.             ja p1_ffinish
  2395.             sub bl,'0'
  2396.             jc p1_ffinish
  2397.  
  2398.             mul cx                  ;Multiply by 10
  2399.             add ax,bx               ;Add in digit...
  2400.             adc dx,0
  2401.             imul di,10              ;Multiply divisor by 10
  2402.             jnc p1_floop            ;Loop while < 5 digits
  2403.  
  2404.             shr dx,1                ;5 digits, divide by 2
  2405.             rcr ax,1                ;and set DI to 50000
  2406.             mov di,50000            ;instead of 100000
  2407.  
  2408. p1_ffinish: xchg dx,ax              ;Multiply by 65536
  2409.             xor ax,ax
  2410.             div di                  ;Divide by 10^digits
  2411.             xchg dx,ax              ;Fractional part in DX
  2412.             pop ax                  ;Restore integer part
  2413.  
  2414. p1_finish:  xchg dx,ax              ;DX:AX = number
  2415.  
  2416.             dec bp                  ;Positive, don't negate
  2417.             jl p1_done
  2418.  
  2419.             neg dx                  ;Negate the result
  2420.             neg ax
  2421.             sbb dx,0
  2422.  
  2423. p1_done:    pop bp di si cx bx      ;Restore registers
  2424.             pop bp                  ;Delete stack frame
  2425.             ret 2                   ;Return
  2426.  
  2427. EndP        atofix
  2428.  
  2429. End
  2430.  
  2431. ~~~C_BITS
  2432. Ideal
  2433.  
  2434. Public      bitcnt,highbit
  2435.  
  2436. Model Tiny
  2437. P186
  2438. CodeSeg
  2439.  
  2440. ;****************** bitcnt() -- Count set bits in integer
  2441. ;int bitcnt(int x);
  2442.  
  2443. x           equ bp+4
  2444.  
  2445. Proc        bitcnt
  2446.  
  2447.             push bp                 ;Set up stack frame
  2448.             mov bp,sp
  2449.             push bx cx              ;Save registers
  2450.  
  2451.             xor cx,cx               ;CX = 0
  2452.             mov ax,[x]              ;AX = number
  2453.             test ax,ax              ;Zero?
  2454.             jz p1_done
  2455.  
  2456. p1_loop:    mov bx,ax               ;Kill last bit
  2457.             dec bx
  2458.             and ax,bx
  2459.             loopnz p1_loop          ;Loop while not zero
  2460.  
  2461. p1_done:    sub ax,cx               ;Negative of CX
  2462.  
  2463.             pop cx bx               ;Restore registers
  2464.             pop bp                  ;Delete stack frame
  2465.             ret 2                   ;Return
  2466.  
  2467. EndP        bitcnt
  2468.  
  2469. ;****************** highbit() -- Find high bit in integer
  2470. ;int highbit(int x);             returns -1 if it was zero
  2471.  
  2472. x           equ bp+4
  2473.  
  2474. Proc        highbit
  2475.  
  2476.             push bp                 ;Set up stack frame
  2477.             mov bp,sp
  2478.             push bx                 ;Save registers
  2479.  
  2480.             mov ax,15               ;Start with bit 15
  2481.             mov bx,[x]              ;BX = number
  2482.  
  2483. p2_loop:    add bx,bx               ;Shift out bit
  2484.             jc p2_done              ;Found a bit?
  2485.             dec ax                  ;Loop back
  2486.             jns p2_loop
  2487.  
  2488. p2_done:    pop bx                  ;Restore registers
  2489.             pop bp                  ;Delete stack frame
  2490.             ret 2                   ;Return
  2491.  
  2492. EndP        highbit
  2493.  
  2494. End
  2495.  
  2496. ~~~C_SQRT
  2497. Ideal
  2498.  
  2499. Public      sqrt
  2500.  
  2501. Model Tiny
  2502. P186
  2503. CodeSeg
  2504.  
  2505. ;****************** sqrt() -- Returns the square root of a
  2506. ;                             long.  Result is an integer.
  2507. ;int sqrt(long num);          60-350 clocks (486)
  2508.  
  2509.  
  2510. num         equ bp+4
  2511.  
  2512. Proc        sqrt
  2513.  
  2514.             push bp                 ;Set up stack frame
  2515.             mov bp,sp
  2516.             push cx dx              ;Save registers
  2517.  
  2518.             mov ax,[num]            ;DX:AX = num
  2519.             mov dx,[num+2]
  2520.  
  2521.             mov cx,32               ;32 bits
  2522.  
  2523. p1_bloop:   add ax,ax               ;Find the highest set bit
  2524.             adc dx,dx
  2525.             jc p1_gotbit
  2526.             loop p1_bloop
  2527.  
  2528. p1_gotbit:  mov ax,1                ;CX = first guess 2^(log2(n)/2)
  2529.             shr cx,1
  2530.             shl ax,cl
  2531.             xchg cx,ax
  2532.  
  2533. p1_loop:    mov ax,[num]            ;DX:AX = num
  2534.             mov dx,[num+2]
  2535.             div cx                  ;AX = num/guess
  2536.             add cx,ax               ;CX = (guess+(num/guess))/2
  2537.             shr cx,1
  2538.             sub ax,cx               ;If the difference is 1
  2539.             cmp ax,1                ;or less, then done
  2540.             ja p1_loop              ;Loop back
  2541.  
  2542.             xchg ax,cx              ;AX = result
  2543.             pop dx cx               ;Restore registers
  2544.             pop bp                  ;Delete stack frame
  2545.             ret 4                   ;Return
  2546.  
  2547. EndP        sqrt
  2548.  
  2549. End
  2550.  
  2551. ~~~C_ROMAN
  2552. Ideal
  2553.  
  2554. Public      roman
  2555.  
  2556. Model Tiny
  2557. CodeSeg
  2558. P386
  2559.  
  2560. ;****************** roman() -- Convert integer to Roman Numerals
  2561.  
  2562. num         equ bp+6
  2563. buf         equ bp+4
  2564.  
  2565. Proc        roman
  2566.  
  2567.             push bp                 ;Set up stack frame
  2568.             mov bp,sp
  2569.             pusha                   ;Save all registers
  2570.  
  2571.             mov di,[buf]            ;DI = buffer
  2572.             mov dx,[num]            ;DX = number
  2573.             mov si,offset RNTbl_1   ;SI, BX = tables
  2574.             mov bx,offset RNTbl_2
  2575.  
  2576. p1_loop:    lodsw                   ;Load size
  2577.             test ax,ax              ;Done?
  2578.             jz p1_done
  2579.  
  2580. p1_iloop:   cmp dx,ax
  2581.             jl p1_lb
  2582.             mov cx,[bx]             ;AX = code
  2583.             mov [di],cl             ;Store first char
  2584.             inc di
  2585.  
  2586.             cmp ch,'.'              ;If second char, then
  2587.             je p1_ilb               ; store second char
  2588.             mov [di],ch
  2589.             inc di
  2590.  
  2591. p1_ilb:     sub dx,ax               ;Reduce number
  2592.             jmp p1_iloop            ;Loop back
  2593.  
  2594. p1_lb:      inc bx                  ;Advance pointer
  2595.             inc bx
  2596.             jmp p1_loop             ;Loop back
  2597.  
  2598. p1_done:    mov [di],al             ;Terminate string
  2599.  
  2600.             popa                    ;Restore registers
  2601.             pop bp                  ;Delete stack frame
  2602.             ret 4                   ;Return
  2603.  
  2604. EndP        roman
  2605.  
  2606. RNTbl_1     dw 1000,900,500,400,100
  2607.             dw 90,50,40,10,9,5,4,1,0
  2608.  
  2609. RNTbl_2     db 'M.CMD.CDC.XCL.XLX.IXV.IVI.'
  2610.  
  2611. End
  2612.  
  2613. ~~~C_CRC16
  2614. Ideal
  2615.  
  2616. Public      crc16
  2617.  
  2618. Model Tiny
  2619. CodeSeg
  2620. P186
  2621.  
  2622. ;****************** crc16() -- Calculate 16-bit CRC
  2623. ;int crc16(void *ptr, int cnt)
  2624.  
  2625. ptr         equ bp+6
  2626. cnt         equ bp+4
  2627.  
  2628. Proc        crc16
  2629.  
  2630.             push bp                 ;Set up stack frame
  2631.             mov bp,sp
  2632.             push bx cx dx si        ;Save registers
  2633.  
  2634.             mov si,[ptr]            ;SI = pointer
  2635.             mov bx,[cnt]            ;BX = count
  2636.  
  2637.             xor dx,dx               ;Start with 0
  2638.  
  2639. p1_loop:    lodsb                   ;Load byte
  2640.             xor dh,al               ;XOR into result
  2641.             mov cx,8                ;8 bits
  2642.  
  2643. p1_iloop:   add dx,dx               ;Shift left
  2644.             jnc $+5                 ;If bit = 1, then
  2645.             xor dx,1021h            ;XOR in CRC value
  2646.             loop p1_iloop           ;Loop back
  2647.  
  2648.             dec bx                  ;Byte loop
  2649.             jnz p1_loop
  2650.  
  2651.             xchg dx,ax              ;Result in AX
  2652.  
  2653. p1_done:    pop si dx cx bx         ;Restore registers
  2654.             pop bp                  ;Delete stack frame
  2655.             ret 4                   ;Return
  2656.  
  2657. EndP        crc16
  2658.  
  2659. End
  2660.  
  2661. ~~~C_CRC32
  2662. Ideal
  2663.  
  2664. Public      crc32
  2665.  
  2666. Model Tiny
  2667. CodeSeg
  2668. P186
  2669.  
  2670. ;****************** crc32() -- Calculate 32-bit CRC
  2671. ;long crc32(void *ptr, int cnt)
  2672.  
  2673. ptr         equ bp+6
  2674. cnt         equ bp+4
  2675.  
  2676. Proc        crc32
  2677.  
  2678.             push bp                 ;Set up stack frame
  2679.             mov bp,sp
  2680.             push bx cx si di        ;Save registers
  2681.  
  2682.             mov si,[ptr]            ;SI = pointer
  2683.             mov bx,[cnt]            ;BX = count
  2684.  
  2685.             xor dx,dx               ;Start with 0
  2686.             xor di,di
  2687.  
  2688. p1_loop:    lodsb                   ;Load byte
  2689.             xor dh,al               ;XOR into result
  2690.             mov cx,8                ;8 bits
  2691.  
  2692. p1_iloop:   add di,di               ;Shift left
  2693.             adc dx,dx
  2694.             jnc $+8                 ;If bit = 1, then
  2695.             xor dx,04C1h            ;XOR in CRC value
  2696.             xor di,1DB7h
  2697.             loop p1_iloop           ;Loop back
  2698.  
  2699.             dec bx                  ;Byte loop
  2700.             jnz p1_loop
  2701.  
  2702.             xchg di,ax              ;Result in DX:AX
  2703.  
  2704. p1_done:    pop di si cx bx         ;Restore registers
  2705.             pop bp                  ;Delete stack frame
  2706.             ret 4                   ;Return
  2707.  
  2708. EndP        crc32
  2709.  
  2710. End
  2711.